#include "../../MyUtils/DataType/ByteArray.hpp"
#include <gtest/gtest.h>

using ByteArray = MyUtils::DataType::ByteArray;

using namespace std;

TEST( ByteArray, ByteArray )
{
    ByteArray a; // default constructor
    EXPECT_EQ( a.size( ), 0 );
    EXPECT_EQ( a.capacity( ), 512 );
    EXPECT_NE( a.data( ), nullptr );

    ByteArray b( size_t(0), 1024 ); // constructor with size
    EXPECT_EQ( b.size( ), 0 );
    EXPECT_EQ( b.capacity( ), 1024 );
    EXPECT_NE( b.data( ), nullptr );
    memset( ( void * ) b.data( ), 1, b.capacity( ) );
    for ( int i = 0; i < b.capacity( ); ++i )
    {
        EXPECT_EQ( ( ( char * ) ( b.data( ) ) )[ i ], 1 );
    }

    ByteArray c( std::move( b ) ); // move constructor
    EXPECT_EQ( c.size( ), 0 );
    EXPECT_EQ( c.capacity( ), 1024 );
    EXPECT_NE( c.data( ), nullptr );
    EXPECT_EQ( b.size( ), 0 );
    EXPECT_EQ( b.capacity( ), 0 );
    EXPECT_EQ( b.data( ), nullptr );
    EXPECT_NE( b.data( ), c.data( ) );
    for ( int i = 0; i < b.capacity( ); ++i )
    {
        EXPECT_EQ( ( ( char * ) ( c.data( ) ) )[ i ], 1 );
    }

    ByteArray d( c ); // shadow copy constructor
    EXPECT_EQ( d.size( ), 0 );
    EXPECT_EQ( d.capacity( ), 1024 );
    EXPECT_NE( d.data( ), nullptr );
    EXPECT_EQ( c.size( ), 0 );
    EXPECT_EQ( c.capacity( ), 1024 );
    EXPECT_NE( c.data( ), nullptr );
    EXPECT_EQ( d.data( ), c.data( ) );
    for ( int i = 0; i < b.capacity( ); ++i )
    {
        EXPECT_EQ( ( ( char * ) ( d.data( ) ) )[ i ], 1 );
    }

    ByteArray e = d; // asignment constructor, shadow copy
    EXPECT_EQ( e.size( ), 0 );
    EXPECT_EQ( e.capacity( ), 1024 );
    EXPECT_NE( e.data( ), nullptr );
    EXPECT_EQ( d.size( ), 0 );
    EXPECT_EQ( d.capacity( ), 1024 );
    EXPECT_NE( d.data( ), nullptr );
    EXPECT_EQ( e.data( ), d.data( ) );
    for ( int i = 0; i < b.capacity( ); ++i )
    {
        EXPECT_EQ( ( ( char * ) ( e.data( ) ) )[ i ], 1 );
    }

    ByteArray f( e.data( ), e.capacity( ) ); // move assignment
    EXPECT_EQ( f.size( ), e.capacity( ) );
    EXPECT_EQ( f.capacity( ), e.capacity( ) );
    EXPECT_NE( f.data( ), e.data( ) );
    EXPECT_NE( f.data( ), nullptr );

    ByteArray g;
    g = e; // asignment
    EXPECT_EQ( g.size( ), e.size( ) );
    EXPECT_EQ( g.capacity( ), e.capacity( ) );
    EXPECT_EQ( g.data( ), e.data( ) );

    ByteArray h = g.clone( ); // deep copy
    EXPECT_EQ( h.size( ), g.size( ) );
    // EXPECT_EQ( h.capacity( ), g.capacity( ) );//不一定
    EXPECT_NE( h.data( ), g.data( ) );
    EXPECT_NE( h.data( ), nullptr );
    for ( int i = 0; i < g.size( ); ++i )
    {
        EXPECT_EQ( ( ( char * ) ( h.data( ) ) )[ i ],
                   ( ( char * ) ( g.data( ) ) )[ i ] );
    }
}

TEST( ByteArray, ByteArray_copy )
{
    ByteArray a( 1024 );
    memset( ( void * ) a.data( ), 1, a.capacity( ) );

    ByteArray b( a ); // shadow copy
    b.reset( );
    EXPECT_EQ( b.size( ), 0 );
    EXPECT_EQ( b.capacity( ), a.capacity( ) );
    EXPECT_EQ( b.data( ), a.data( ) );
    for ( int i = 0; i < b.capacity( ); ++i )
    {
        EXPECT_EQ( ( ( char * ) ( b.data( ) ) )[ i ], 1 );
    }

    ByteArray c;
    c.copy( b ); // copy
    EXPECT_EQ( c.size( ), b.size( ) );
    // EXPECT_EQ( c.capacity( ), b.capacity( ) );//二者不一定相等
    EXPECT_NE( c.data( ), b.data( ) ); //二者一定不相等
    memset( ( void * ) c.data( ), 2, c.capacity( ) );
    for ( int i = 0; i < b.capacity( ); ++i )
    {
        EXPECT_EQ( ( ( char * ) ( b.data( ) ) )[ i ], 1 );
    }
    for ( int i = 0; i < c.capacity( ); ++i )
    {
        EXPECT_EQ( ( ( char * ) ( c.data( ) ) )[ i ], 2 );
    }

    char d[] = "hello";
    ByteArray e( ( unsigned char * ) d, strlen( d ) );
    EXPECT_EQ( e.size( ), strlen( d ) );
    EXPECT_EQ( e.capacity( ),
               8 ); // strlen( d ) == 5，不是2的指数，将其扩增到2的指数
    EXPECT_NE( e.data( ), nullptr );
    EXPECT_NE( ( void * ) e.data( ), ( void * ) d );

    ByteArray f = e.clone( ); // deep copy
    EXPECT_EQ( f.size( ), e.size( ) );
    EXPECT_EQ( f.capacity( ), 8 );
    EXPECT_NE( f.data( ), e.data( ) );

    char g[ 1023 ];
    memset( g, 1, 1023 );
    ByteArray h;
    h.copy( ( unsigned char * ) g, 1020 ); // copy
    EXPECT_EQ( h.size( ), 1020 );
    EXPECT_EQ( h.capacity( ),
               1024 ); //默认初始化为512，容量需要扩增到最近的2的指数即1024
}

TEST( ByteArray, ByteArray_append )
{
    ByteArray a( 1024 );
    memset( ( void * ) a.data( ), 1, a.capacity( ) );

    ByteArray b( a ); // shadow copy
    a.reset();
    EXPECT_EQ( b.size( ), a.size( ) );
    EXPECT_EQ( b.capacity( ), a.capacity( ) );
    EXPECT_EQ( b.data( ), a.data( ) );
    for ( int i = 0; i < b.capacity( ); ++i )
    {
        EXPECT_EQ( ( ( char * ) ( b.data( ) ) )[ i ], 1 );
    }

    char c[] = "hello";
    b.append( ( unsigned char * ) c, strlen( c ) );
    EXPECT_EQ( b.size( ), strlen( c ) );
    EXPECT_EQ( b.size( ), a.size( ) );
    EXPECT_EQ( b.capacity( ), a.capacity( ) );
    EXPECT_EQ( b.data( ), a.data( ) );

    char d[] = "world";
    b.append( ( unsigned char * ) d, strlen( d ) );
    EXPECT_EQ( b.size( ), strlen( c ) + strlen( d ) );
    EXPECT_EQ( b.size( ), a.size( ) );
    EXPECT_EQ( b.capacity( ), a.capacity( ) );
    EXPECT_EQ( b.data( ), a.data( ) );

    ByteArray e = ByteArray::append( ( unsigned char * ) c, strlen( c ),
                                     ( unsigned char * ) d, strlen( d ) );
    EXPECT_EQ( e.size( ), strlen( c ) + strlen( d ) );
    EXPECT_EQ( e.size( ), a.size( ) );
}

TEST( ByteArray, ByteArray_swap )
{
    ByteArray a( ( unsigned char * ) "hello", 5 );
    ByteArray b( ( unsigned char * ) "hello world", 11 );
    a.swap( b );
    EXPECT_EQ( a.size( ), 11 );
    EXPECT_EQ( b.size( ), 5 );
}

TEST( ByteArray, ByteArray_clear )
{
    ByteArray a( ( unsigned char * ) "hello", 5 );
    auto b = a;
    a.clear( );
    EXPECT_EQ( a.size( ), 0 );
    EXPECT_EQ( a.capacity( ), 8 );
    EXPECT_NE( a.data( ), nullptr );

    EXPECT_EQ( b.size( ), a.size( ) );
    EXPECT_EQ( b.capacity( ), a.capacity( ) );
    EXPECT_EQ( b.data( ), a.data( ) );
}

TEST( ByteArray, ByteArray_slice )
{
    ByteArray a( 11 );
    for ( int i = 0; i < 11; ++i )
    {
        ( ( char * ) a.data( ) )[ i ] = i;
    }
    ByteArray b = a.slice( 1, 6 );
    EXPECT_EQ( b.size( ), 5 );
    EXPECT_EQ( b.capacity( ), 8 );
    EXPECT_NE( b.data( ), nullptr );
    EXPECT_NE( b.data( ), a.data( ) );
    for ( int i = 0; i < b.size( ); ++i )
    {
        EXPECT_EQ( ( ( char * ) ( b.data( ) ) )[ i ], i + 1 );
    }
}

TEST( ByteArray, ByteArray_append_char_and_index )
{
    ByteArray a;
    a.append( 'a' );
    a.append( 'b' );
    a.append( 'c' );
    a.append( 'd' );
    a.append( 'e' );
    a.append( 'f' );
    a.append( 'g' );

    EXPECT_EQ( a.size( ), 7 );
    EXPECT_EQ( a[ 0 ], 'a' );
    EXPECT_EQ( a[ 1 ], 'b' );
    EXPECT_EQ( a[ 2 ], 'c' );
    EXPECT_EQ( a[ 3 ], 'd' );
    EXPECT_EQ( a[ 4 ], 'e' );
    EXPECT_EQ( a[ 5 ], 'f' );
    EXPECT_EQ( a[ 6 ], 'g' );
}
